﻿#include "OiPCH.hpp"
#include "OiTool.hpp"
#include "OiChart.hpp"

#define lineProtrusion 0.5
#define arrowLength 15

namespace Oi
{
    namespace Appl
    {
        class ToolImpl : public Impl<Tool>
        {
        public:
            void init();
            void exit();

        public:
            QtCharts::QChart* _chart = NULL;
            DataViewer* _dataViewer = NULL;

            //0 ==NA, 1==NG, 2==OK, 3==Warning
            int _status = 0;

            double _result;
            double _min;
            double _max;
            QString _name;
            QColor _toolColor = Qt::white;
            TestTool* _text;
            LTBase::AlgoOutput _output;
            QPointF _latchPoint = QPointF(0, 0);
            QPointF _anchorPoint = QPointF(0, 0);
            bool _displayDataViewer = false;

            QRectF _boundingRect;
            DisplayMode _displayMode = DETAILED;
        };

        Tool::Tool(QGraphicsItem *parent, QtCharts::QChart* chart, qreal x, qreal y, qreal width, qreal height) : QGraphicsObject(parent)
        {
            OI_F(Tool);
            d->_chart = chart;
            setFlag(QGraphicsItem::ItemIsSelectable, true);
            d->_text = new TestTool(this);
            QObject::connect(d->_text, &TestTool::requestContextMenu, this, &Tool::requestContextMenu);
            d->_text->setDefaultTextColor(Qt::white);
            QFont font = d->_text->font();
            font.setPointSizeF(30);
            d->_text->setFont(font);
            d->_boundingRect = QRectF(x, y, width, height);
        }

        Tool::~Tool()
        {
            OI_F(Tool);
            if (d->_dataViewer)
            {
                d->_dataViewer->deleteLater();
            }
        }

        void Tool::manualUpdate(QPoint)
        {
            update();
        }

        void Tool::mousePressEvent(QGraphicsSceneMouseEvent *event)
        {
            OI_F(Tool);
        }

        void Tool::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
        {
            OI_F(Tool);
            if (!d->_dataViewer) return;
            requestContextMenu(event->screenPos());
        }

        QRectF Tool::boundingRect() const
        {
            OI_C(Tool);
            return d->_boundingRect;
        }

        void Tool::requestContextMenu(QPoint globalpoint)
        {
            OI_F(Tool);

            QMenu menu;
            menu.addAction(Tool::tr("简洁数值"));
            menu.addAction(Tool::tr("详细数值"));
            menu.addAction(Tool::tr("折线图"));
            menu.addAction(Tool::tr("简洁数值+折线图"));
            menu.addAction(Tool::tr("详细数值+折线图"));

            QAction* action = menu.exec(globalpoint);

            if (!action) return;

            if (action->text() == Tool::tr("简洁数值"))
            {
                setDisplayMode(DisplayMode::SIMPLE);
            }

            if (action->text() == Tool::tr("详细数值"))
            {
                setDisplayMode(DisplayMode::DETAILED);
            }

            if (action->text() == Tool::tr("简洁数值+折线图"))
            {
                setDisplayMode(DisplayMode::SIMPLE_GRAPH);
            }

            if (action->text() == Tool::tr("详细数值+折线图"))
            {
                setDisplayMode(DisplayMode::DETAILED_GRAPH);
            }

            if (action->text() == Tool::tr("折线图"))
            {
                setDisplayMode(DisplayMode::GRAPH);
            }

            emit settingChanged();
        }

        void Tool::drawLine(QPainter* painter, const QPointF &startPoint, const QPointF &endPoint, QColor color, qreal width)
        {
            OI_F(Tool);

            QPen pen(color, width);
            painter->setPen(pen);
            painter->drawLine(mapFromParent(d->_chart->mapToPosition(startPoint)), mapFromParent(d->_chart->mapToPosition(endPoint)));
        }

        void Tool::drawArrow(QPainter* painter, QColor color, const QPointF &arrowTip, const QPointF &arrowEnd, const double &angle, const double &length)
        {
            OI_F(Tool);

            QPointF tip = mapFromParent(d->_chart->mapToPosition(arrowTip));
            QPointF direction = tip - mapFromParent(d->_chart->mapToPosition(arrowEnd));

            double cosAngle1 = std::cos(CV_PI - angle * CV_PI / 360.0);
            double sinAngle1 = std::sin(CV_PI - angle * CV_PI / 360.0);
            double cosAngle2 = std::cos(CV_PI + angle * CV_PI / 360.0);
            double sinAngle2 = std::sin(CV_PI + angle * CV_PI / 360.0);
            QPointF arrow1 = QPointF(direction.x()*cosAngle1 - direction.y()*sinAngle1, direction.x()*sinAngle1 + direction.y()*cosAngle1);
            QPointF arrow2 = QPointF(direction.x()*cosAngle2 - direction.y()*sinAngle2, direction.x()*sinAngle2 + direction.y()*cosAngle2);
            QPointF arrow3 = direction * 0.8 * length / std::sqrt(direction.x()*direction.x() + direction.y()*direction.y());
            arrow1 = arrow1 * length / std::sqrt(arrow1.x()*arrow1.x() + arrow1.y()*arrow1.y());
            arrow2 = arrow2 * length / std::sqrt(arrow2.x()*arrow2.x() + arrow2.y()*arrow2.y());

            QPainterPath path(tip);

            path.lineTo(tip + arrow1);
            path.lineTo(tip - arrow3);
            path.lineTo(tip + arrow2);
            path.lineTo(tip);

            painter->fillPath(path, color);
        }

        void Tool::paint(QPainter * painter, const QStyleOptionGraphicsItem * o, QWidget * w)
        {
            OI_F(Tool);

            painter->setRenderHint(QPainter::Antialiasing);
            
            updateLatchPoint();

            //draw tool
            switch (d->_output.tool.type)
            {
            case LTBase::E_TT_ERRORMAX:
            case LTBase::E_TT_ERRORMEAN:
            case LTBase::E_TT_ERRORRMS:
            case LTBase::E_TT_AREA:
                if (d->_output.tool.data.size() < 4)
                {
                    break;
                }
                for (int i = 0; i < d->_output.displayData.size() / 2; i++)
                {
                    drawLine(painter, d->_output.displayData[i * 2], d->_output.displayData[i * 2 + 1], Qt::red, 1);
                }
                for (int i = 0; i < 4; i++)
                {
                    drawLine(painter, d->_output.tool.data[i], d->_output.tool.data[(i + 1) % 4], d->_toolColor, 1);
                }

                if (d->_displayMode == DisplayMode::SIMPLE || d->_displayMode == DisplayMode::SIMPLE_GRAPH)
                {
                    //d->_dataViewer->show();
                    d->_text->setVisible(true);

                    double orientation = (mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[0])) - mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[1]))).y() / (mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[0])) - mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[1]))).x();

                    QPointF newPos = mapFromParent(d->_chart->mapToPosition((d->_output.tool.data[0] + d->_output.tool.data[1]) / 2));

                    if ((newPos - d->_text->pos()).manhattanLength() > 5)
                    {
                        d->_text->setPos(newPos);
                        QRectF textRect = d->_text->boundingRect();
                        QPointF textCenter = QPointF(textRect.x() + textRect.width() / 2, textRect.y() + textRect.height() / 2);
                        QTransform t;
                        t.rotate(std::atan(orientation) / CV_PI * 180.0);
                        t.translate(-textCenter.x(), -textCenter.y() * 1.6);
                        d->_text->setTransform(t);
                    }
                }
                else
                {
                    d->_text->setVisible(false);
                }
                
                break;
            case LTBase::E_TT_OUTSIDECALIPER:
            case LTBase::E_TT_CALIPERPAIR:
                if (d->_output.displayData.size() != 4)
                {
                    if (d->_displayMode == DisplayMode::SIMPLE || d->_displayMode == DisplayMode::SIMPLE_GRAPH)
                    {
                        d->_text->setVisible(true);
                    }
                    else
                    {
                        d->_text->setVisible(false);
                    }

                    for (int k = 0; k < d->_output.tool.data.size() / 4; k++)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            int index1 = k * 4 + i;
                            int index2 = k * 4 +  ((i + 1) % 4);

                            if (index1 >= d->_output.tool.data.size())continue;
                            if (index2 >= d->_output.tool.data.size())continue;

                            drawLine(painter, d->_output.tool.data[index1], d->_output.tool.data[index2], d->_toolColor, 1);

                        }
                    }
                    break;
                }

                drawLine(painter, d->_output.displayData[0] + lineProtrusion * (d->_output.displayData[0] - d->_output.displayData[3]) / std::sqrt((d->_output.displayData[0] - d->_output.displayData[3]).x() * (d->_output.displayData[0] - d->_output.displayData[3]).x() + (d->_output.displayData[0] - d->_output.displayData[3]).y() * (d->_output.displayData[0] - d->_output.displayData[3]).y()), d->_output.displayData[3], d->_toolColor, 1);
                drawLine(painter, d->_output.displayData[1] + lineProtrusion * (d->_output.displayData[1] - d->_output.displayData[2]) / std::sqrt((d->_output.displayData[1] - d->_output.displayData[2]).x() * (d->_output.displayData[1] - d->_output.displayData[2]).x() + (d->_output.displayData[1] - d->_output.displayData[2]).y() * (d->_output.displayData[1] - d->_output.displayData[2]).y()), d->_output.displayData[2], d->_toolColor, 1);
                drawLine(painter, d->_output.displayData[1], d->_output.displayData[2], d->_toolColor, 1);
                drawArrow(painter, d->_toolColor, d->_output.displayData[0], d->_output.displayData[1], 30, arrowLength);
                drawArrow(painter, d->_toolColor, d->_output.displayData[1], d->_output.displayData[0], 30, arrowLength);
                drawLine(painter, d->_output.displayData[0], d->_output.displayData[1], d->_toolColor, 1);

                if (d->_displayMode == DisplayMode::SIMPLE || d->_displayMode == DisplayMode::SIMPLE_GRAPH)
                {
                    d->_text->setVisible(true);

                    double orientation = (mapFromParent(d->_chart->mapToPosition(d->_output.displayData[1])) - mapFromParent(d->_chart->mapToPosition(d->_output.displayData[0]))).y() / (mapFromParent(d->_chart->mapToPosition(d->_output.displayData[1])) - mapFromParent(d->_chart->mapToPosition(d->_output.displayData[0]))).x();

                    if ((d->_latchPoint - d->_text->pos()).manhattanLength() > 5)
                    {
                        d->_text->setPos(d->_latchPoint);
                        QRectF textRect = d->_text->boundingRect();
                        QPointF textCenter = QPointF(textRect.x() + textRect.width() / 2, textRect.y() + textRect.height() / 2);
                        QTransform t;
                        t.rotate(std::atan(orientation) / CV_PI * 180.0);
                        t.translate(-textCenter.x(), -textCenter.y() * 1.6);
                        d->_text->setTransform(t);
                    }
                }
                else
                {
                    d->_text->setVisible(false);
                }
                break;
            }
            
            QPen pen;

            //draw textbox
            if (d->_displayMode == DisplayMode::DETAILED || d->_displayMode == DisplayMode::DETAILED_GRAPH)
            {
                QPainterPath path, minPath, maxPath, namePath;
                QRectF minValueBoundingRect = QRectF(boundingRect().bottomLeft(), QSizeF(boundingRect().width() / 2, boundingRect().height() / 4));
                QRectF maxValueBoundingRect = QRectF(boundingRect().bottomLeft() + QPointF(boundingRect().width() / 2, 0), QSizeF(boundingRect().width() / 2, boundingRect().height() / 4));
                QRectF nameBoundingRect = QRectF(boundingRect().topLeft() - QPointF(0, boundingRect().height() / 4), QSizeF(boundingRect().width(), boundingRect().height() / 4));

               
                path.addRect(boundingRect());
                minPath.addRect(minValueBoundingRect);
                maxPath.addRect(maxValueBoundingRect);
                namePath.addRect(nameBoundingRect);
                
                if (d->_status == 0)
                {
                    pen = QPen(Qt::black, 1);
                    painter->fillPath(path, Qt::lightGray);
                    painter->fillPath(minPath, Qt::darkGray);
                    painter->fillPath(maxPath, Qt::darkGray);
                    painter->fillPath(namePath, Qt::darkGray);
                }
                else if (d->_status == 1)
                {
                    pen = QPen(Qt::black, 1);
                    painter->fillPath(path, Qt::red);
                    painter->fillPath(minPath, Qt::darkRed);
                    painter->fillPath(maxPath, Qt::darkRed);
                    painter->fillPath(namePath, Qt::darkRed);
                }
                else if (d->_status == 3)
                {
                    pen = QPen(Qt::black, 1);
                    painter->fillPath(path, QColor(255, 215, 0));
                    painter->fillPath(minPath, QColor(255, 180, 0));
                    painter->fillPath(maxPath, QColor(255, 180, 0));
                    painter->fillPath(namePath, QColor(255, 180, 0));
                }
                else
                {
                    pen = QPen(Qt::black, 1);
                    painter->fillPath(path, Qt::lightGray);
                    painter->fillPath(minPath, Qt::darkGray);
                    painter->fillPath(maxPath, Qt::darkGray);
                    painter->fillPath(namePath, Qt::darkGray);
                }
                painter->setPen(pen);

                QFont font = painter->font();
                font.setPointSizeF(this->boundingRect().height() * 0.15);
                painter->setFont(font);

                if (d->_output.tool.toleranceType == LTBase::ToleranceType::BILATERALTOLERANCE)
                {
                    painter->drawText(nameBoundingRect, Qt::AlignCenter, d->_name);//need checking
                    painter->drawText(minValueBoundingRect, Qt::AlignCenter, Tool::tr("基本尺寸 = ") + QString::number(d->_output.tool.basicSize, 'f', 2));
                    painter->drawText(maxValueBoundingRect, Qt::AlignCenter, Tool::tr("对称公差 = ±") + QString::number((d->_output.tool.maxval - d->_output.tool.minval) * 0.5, 'f', 2));
                }
                else
                {
                    painter->drawText(nameBoundingRect, Qt::AlignCenter, d->_name);//need checking
                    painter->drawText(minValueBoundingRect, Qt::AlignCenter, Tool::tr("下限 = ") + QString::number(d->_min));
                    painter->drawText(maxValueBoundingRect, Qt::AlignCenter, Tool::tr("上限 = ") + QString::number(d->_max));
                }


                font = painter->font();
                font.setPointSizeF(this->boundingRect().height() * 0.75);
                painter->setFont(font);
                painter->drawText(this->boundingRect(), Qt::AlignCenter, QString::number(d->_result, 'f', 2), &(this->boundingRect()));
            }
            
            //draw hint
            if (d->_displayMode == DisplayMode::DETAILED || d->_displayMode == DisplayMode::DETAILED_GRAPH)
            {
                if (d->_status == 0 || d->_status == 2)
                {
                    if (this->isSelected())
                    {
                        pen = QPen(Qt::lightGray, 2);
                        pen.setStyle(Qt::SolidLine);
                    }
                    else
                    {
                        pen = QPen(Qt::gray, 0.5);
                        pen.setStyle(Qt::DashDotDotLine);

                    }
                }
                else if (d->_status == 1)
                {
                    pen = QPen(Qt::red, 2);
                    pen.setStyle(Qt::SolidLine);
                }
                else if (d->_status == 3)
                {
                    pen = QPen(QColor(255, 215, 0), 2);
                    pen.setStyle(Qt::SolidLine);
                }


                //pen.setStyle(Qt::DashDotDotLine);
                painter->setPen(pen);

                painter->drawLine(d->_anchorPoint, d->_latchPoint);

                painter->drawEllipse(d->_latchPoint, 3, 3);
            }

            if (d->_dataViewer && d->_dataViewer->isVisible())
            {
                if (!scene()->views().isEmpty())
                {
                    QGraphicsView* view = scene()->views().first();
                    auto dataViewerPos = mapFromScene(view->mapToScene(view->viewport()->mapFromGlobal(d->_dataViewer->mapToGlobal(QPoint(0, 0)))));
                    auto dataViewerRect = d->_dataViewer->rect();
                    QList<QPointF> dataViewerPoints = { dataViewerPos, dataViewerPos + QPointF(dataViewerRect.width(),0), dataViewerPos + QPointF(0, dataViewerRect.height()), dataViewerPos + QPointF(dataViewerRect.width(),dataViewerRect.height()) };
                    auto lPoint = latchPoint();
                    auto minDistance = (lPoint - dataViewerPos).manhattanLength();
                    auto minPoint = dataViewerPos;

                    for (int i = 0; i < 4; i++)
                    {
                        auto distance = (lPoint - dataViewerPoints[i]).manhattanLength();
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            minPoint = dataViewerPoints[i];
                        }
                    }
//                    pen = QPen(Qt::gray, 0.5);
                    pen = QPen(Qt::red, 1);
                    pen.setStyle(Qt::DashDotDotLine);
                    painter->setPen(pen);
                    painter->drawLine(minPoint, latchPoint());



                }
                //d->_dataViewer->rect();
                //painter->drawLine(mapFromScene(d->_dataViewer->pos()), latchPoint());
            }

            //QGraphicsRectItem::paint(painter, o, w);
        }

        void Tool::updateResult(double result)
        {
            if (result < 0)
            {
                this->setVisible(false);
            }
        }

        void Tool::setOutput(LTBase::AlgoOutput & output)
        {
            OI_F(Tool);

            d->_output = output;
            d->_result = output.result;
            d->_min = (output.tool.minval);
            d->_max = (output.tool.maxval);
            d->_name = (output.tool.name);
            d->_text->setPlainText(QString::number(d->_result, 'f', 2));

            if (d->_dataViewer)
            {
                d->_dataViewer->updateDisplayData(output.result);
            }

            //if (d->_dataViewer)
            {
               // d->_dataViewer->updateData(d->_result);
            }

            bool alarm = false;
            if (output.result > 0)
            {
                if ((output.tool.maxval > 0) && (output.result > output.tool.maxval))
                    alarm = true;
                if ((output.tool.minval > 0) && (output.result < output.tool.minval))
                    alarm = true;
            }
            else
            {
                if ((output.tool.maxval > 0) || (output.tool.minval > 0)) alarm = true;
            }

            bool warning = false;
            if (output.result > 0)
            {
                if ((output.tool.warningUpper > 0) && (output.result > output.tool.warningUpper))
                    warning = true;
                if ((output.tool.warningLower > 0) && (output.result < output.tool.warningLower))
                    warning = true;
            }


            if (alarm)
            {
                d->_status = 1;
                d->_toolColor = Qt::red;
            }
            else if (warning)
            {
                d->_status = 3;
                d->_toolColor = QColor(255, 215, 0);
            }
            else if (output.tool.maxval > 0 || output.tool.minval > 0 || output.tool.warningLower > 0 || output.tool.warningUpper > 0)
            {
                d->_status = 2;
                d->_toolColor = Qt::white;
            }
            else
            {
                d->_status = 0;
                d->_toolColor = Qt::white;
            }

            d->_text->setDefaultTextColor(d->_toolColor);

            updateLatchPoint();
        }

        void Tool::updateLatchPoint()
        {
            OI_F(Tool);

            QList<QPointF> latchPointCandidates;
            QList<QPointF> anchorPointCandidates = {this->boundingRect().topLeft(),this->boundingRect().topRight() ,this->boundingRect().bottomLeft() ,this->boundingRect().bottomRight() };

            switch (d->_output.tool.type)
            {
            case LTBase::E_TT_ERRORMAX:
            case LTBase::E_TT_ERRORMEAN:
            case LTBase::E_TT_ERRORRMS:
            case LTBase::E_TT_AREA:
                if (d->_output.tool.data.size() != 4)
                {
                    d->_latchPoint = QPointF(0, 0);
                    d->_anchorPoint = QPointF(0, 0);
                    break;
                }
                latchPointCandidates << mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[0]))
                                     << mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[1]))
                                     << mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[2]))
                                     << mapFromParent(d->_chart->mapToPosition(d->_output.tool.data[3]));
                break;
            case LTBase::E_TT_OUTSIDECALIPER:
            case LTBase::E_TT_CALIPERPAIR:
                if (d->_output.displayData.size() != 4)
                {
                    d->_latchPoint = QPointF(0, 0);
                    d->_anchorPoint = QPointF(0, 0);
                    break;
                }
                latchPointCandidates << mapFromParent(d->_chart->mapToPosition((d->_output.displayData[0] + d->_output.displayData[1]) / 2.0));
                break;
            default:
                d->_latchPoint = QPointF(0, 0);
                d->_anchorPoint = QPointF(0, 0);
                break;
            }

            float minDistance = std::numeric_limits<float>::max();

            for (auto latchPoint : latchPointCandidates)
            {
                for (auto anchorPoint : anchorPointCandidates)
                {
                    float tempDistance = QPointF::dotProduct(anchorPoint - latchPoint, anchorPoint - latchPoint);
                    if (tempDistance < minDistance)
                    {
                        minDistance = tempDistance;
                        d->_latchPoint = latchPoint;
                        d->_anchorPoint = anchorPoint;
                    }
                }
            }

        }

        QPointF Tool::latchPoint()
        {
            OI_F(Tool);

            return  d->_latchPoint;
        }

        void Tool::setFontSize(int fontSize)
        {
            OI_F(Tool);
            return;
            QRectF oldTextRect = d->_text->boundingRect();
            QPointF oldTextCenter = QPointF(oldTextRect.x() + oldTextRect.width() / 2, oldTextRect.y() + oldTextRect.height() / 2);
            QFont font = d->_text->font();
            font.setPointSizeF(fontSize);
            d->_text->setFont(font);
            QRectF textRect = d->_text->boundingRect();
            QPointF textCenter = QPointF(textRect.x() + textRect.width() / 2, textRect.y() + textRect.height() / 2);
            QTransform t = d->_text->transform();
            t.translate(oldTextCenter.x() - textCenter.x(), (oldTextCenter.y() - textCenter.y()) * 1.6);
            d->_text->setTransform(t);
        }

        //void Tool::setDisplayModeSimple(bool flag)
        //{
        //    OI_F(Tool);
        //    if (flag)
        //    {
        //        setRect(0, 0, 0, 0);
        //    }
        //    d->_displayModeSimple = flag;
        //}

        //bool Tool::displayModeSimple()
        //{
        //    OI_F(Tool);
        //    return d->_displayModeSimple;
        //}

        void Tool::setDisplayMode(DisplayMode displayMode)
        {
            OI_F(Tool);
            d->_displayMode = displayMode;

            switch (displayMode)
            {
            case DisplayMode::SIMPLE:
                if (d->_dataViewer) d->_dataViewer->hide();
                d->_displayDataViewer = false;
                d->_text->setVisible(true);
                setRect(0, 0, 0, 0);
                break;
            case DisplayMode::DETAILED:
                if (d->_dataViewer) d->_dataViewer->hide();
                d->_displayDataViewer = false;
                d->_text->setVisible(false);
                break;
            case DisplayMode::SIMPLE_GRAPH:
                if (d->_dataViewer) d->_dataViewer->show();
                d->_displayDataViewer = true;
                setRect(0, 0, 0, 0);
                d->_text->setVisible(true);
                break;
            case DisplayMode::DETAILED_GRAPH:
                if (d->_dataViewer) d->_dataViewer->show();
                d->_displayDataViewer = true;
                d->_text->setVisible(false);
                break;
            case DisplayMode::GRAPH:
                if (d->_dataViewer) d->_dataViewer->show();
                d->_displayDataViewer = true;
                d->_text->setVisible(false);
                setRect(0, 0, 0, 0);
                break;
            }

            auto chart = static_cast<Chart*>(d->_chart);
            chart->alignTools();
            update();
        }

        DisplayMode Tool::displayMode()
        {
            OI_F(Tool);
            return d->_displayMode;
        }

        bool Tool::hasDetailedLabel()
        {
            OI_F(Tool);

            if (d->_displayMode == DisplayMode::DETAILED || d->_displayMode == DisplayMode::DETAILED_GRAPH)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        double Tool::min()
        {
            OI_F(Tool);

            return d->_min;
        }

        double Tool::max()
        {
            OI_F(Tool);

            return d->_max;
        }

        void Tool::setDataViewer(DataViewer* viewer)
        {
            OI_F(Tool);

            d->_dataViewer = viewer;
            QObject::connect(viewer, &DataViewer::moved, this, &Tool::manualUpdate);
            QObject::connect(viewer, &DataViewer::requestContextMenu, this, &Tool::requestContextMenu);
        }

        DataViewer* Tool::dataViewer()
        {
            OI_F(Tool);
            return d->_dataViewer;
        }

        QString Tool::name()
        {
            OI_F(Tool);

            return d->_name;
        }

        void Tool::setName(QString name)
        {
            OI_F(Tool);

            d->_name = name;
        }

        void Tool::updateDataviewer(LTBase::AlgoOutput& output)
        {
            OI_F(Tool);

            if (d->_dataViewer)
            {
                d->_dataViewer->updateData(output.result);
            }
        }

        void Tool::setRect(qreal x, qreal y, qreal width, qreal height)
        {
            OI_F(Tool);
            d->_boundingRect = QRectF(x, y, width, height);
        }

        void Tool::hideDataViewer()
        {
            OI_F(Tool);
            if (d->_dataViewer)
            {
                if (d->_displayDataViewer)
                {
                    d->_dataViewer->hide();
                }
            }
        }

        void Tool::showDataViewer()
        {
            OI_F(Tool);
            if (d->_dataViewer)
            {
                if (d->_displayDataViewer)
                {
                    d->_dataViewer->show();
                }
            }
        }

        TestTool::TestTool(QGraphicsItem* parent) : QGraphicsTextItem(parent)
        {
            
        }

        void TestTool::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
        {
            emit requestContextMenu(event->screenPos());
        }

    }
}

